package com.atguigu.gmall.realtime.app.marketing.func;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.realtime.app.marketing.bean.GmallEvent;
import com.atguigu.gmall.realtime.app.marketing.bean.MarketingRuleAllInfo;
import lombok.Data;
import lombok.Setter;
import org.roaringbitmap.RoaringBitmap;
import redis.clients.jedis.Jedis;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static com.atguigu.gmall.realtime.app.marketing.constant.MarketingConst.*;


public class RuleMatcher {

    Jedis jedis;

    public RuleMatcher(Jedis jedis){
        this.jedis=jedis;
    }


    //  1  符合触发事件
    //  2  符合分群集合
    //  3  符合当日行为的条件

    @Setter
    List<MarketingRuleAllInfo>  ruleAllInfoList;

    //根据事件进行匹配 获得匹配的规则清单 可能0或多个
    public List<MarketingRuleAllInfo> match(GmallEvent gmallEvent){
        List<MarketingRuleAllInfo> matchedRuleList   = new ArrayList<>();

        for (MarketingRuleAllInfo marketingRuleAllInfo : ruleAllInfoList) {
            //  1  符合触发事件
            if( !checkTriggerEvent(  marketingRuleAllInfo ,  gmallEvent)){
                continue;
            }
            //  2  符合分群集合
            if( !checkUserGroup(  marketingRuleAllInfo ,  gmallEvent)){
                continue;
            }

            //  3  符合当日行为的条件
            if( !checkUserAction(  marketingRuleAllInfo ,  gmallEvent)){
                continue;
            }

            matchedRuleList.add(marketingRuleAllInfo);
        }
        return matchedRuleList;

    }


    // 是否符合触发事件
    private boolean  checkTriggerEvent(MarketingRuleAllInfo marketingRuleAllInfo ,GmallEvent event){
        if(marketingRuleAllInfo.getTriggerEvent().equals(EVENT_HOME)) {
            if(event.getTopic().equals(TOPIC_PAGE)){
                JSONObject jsonObject = event.getData();
                String pageId = jsonObject.getJSONObject("page").getString("page_id");
                if(pageId.equals("home")){
                    return true;
                }
            }
        } else if (marketingRuleAllInfo.getTriggerEvent().equals(EVENT_PAGE)) {
            if(event.getTopic().equals(TOPIC_PAGE)){
                return true;
            }
        } else if (marketingRuleAllInfo.getTriggerEvent().equals(EVENT_DETAIL)) {
            if(event.getTopic().equals(TOPIC_PAGE)){
                JSONObject jsonObject = event.getData();
                String pageId = jsonObject.getJSONObject("page").getString("page_id");
                if(pageId.equals("good_detail")){
                    return true;
                }
            }
        }else if (marketingRuleAllInfo.getTriggerEvent().equals(EVENT_PAY)) {
            if(event.getTopic().equals(TOPIC_PAGE)){
                JSONObject jsonObject = event.getData();
                String pageId = jsonObject.getJSONObject("page").getString("page_id");
                if(pageId.equals("payment")){
                    return true;
                }
            }
        }else if (marketingRuleAllInfo.getTriggerEvent().equals(EVENT_ORDER)) {
            if(event.getTopic().equals(TOPIC_PAGE)){
                JSONObject jsonObject = event.getData();
                String pageId = jsonObject.getJSONObject("page").getString("page_id");
                if(pageId.equals("trade")){
                    return true;
                }
            }
        }else if (marketingRuleAllInfo.getTriggerEvent().equals(EVENT_CART)) {
            if(event.getTopic().equals(TOPIC_ACTION)){
                JSONObject jsonObject = event.getData();
                String actionId = jsonObject.getJSONObject("action").getString("action_id");
                if(actionId.equals("cart_add")){
                    return true;
                }
            }
        }else if (marketingRuleAllInfo.getTriggerEvent().equals(EVENT_FAVOR)) {
            if(event.getTopic().equals(TOPIC_ACTION)){
                JSONObject jsonObject = event.getData();
                String actionId = jsonObject.getJSONObject("action").getString("action_id");
                if(actionId.equals("favor")){
                    return true;
                }
            }
        }
       return false;
    }

    // 提取uid 判断是否在人群bitmap中
    private boolean  checkUserGroup(MarketingRuleAllInfo marketingRuleAllInfo ,GmallEvent event){
        if(event.getTopic().equals(TOPIC_START)
        ||event.getTopic().equals(TOPIC_ACTION)
        ||event.getTopic().equals(TOPIC_PAGE)){
            String uid = event.getData().getJSONObject("common").getString("uid");
            RoaringBitmap userGroupBitmap = marketingRuleAllInfo.getUserGroupBitmap();

           return   userGroupBitmap.contains(Integer.valueOf(uid));
        }
        return false;
    }

    //  3  符合当日行为的条件
    private boolean  checkUserAction(MarketingRuleAllInfo marketingRuleAllInfo ,GmallEvent event){
        List<JSONObject> userActionList = marketingRuleAllInfo.getUserActionList();
        if(event.getTopic().equals(TOPIC_START)
                ||event.getTopic().equals(TOPIC_ACTION)
                ||event.getTopic().equals(TOPIC_PAGE)) {
            String uid = event.getData().getJSONObject("common").getString("uid");
            //    从redis中获取该用户当日行为的统计
            String key="user_action:uid:"+uid;
            Map<String, String> userActionMap = jedis.hgetAll(key);

            for (JSONObject conditionJsonObj : userActionList) {
                String actionKey = conditionJsonObj.getString("userAction");
                String todayActionAmountString = userActionMap.get(actionKey);
                Long todayActionAmount=0L;
                if(todayActionAmountString!=null){
                    todayActionAmount=Long.valueOf(todayActionAmountString);
                }
                Long actionAmount = conditionJsonObj.getLong("actionAmount");
                String operator = conditionJsonObj.getString("operator");
                boolean ifMatch = compareWithOperator( todayActionAmount, operator, actionAmount);
                if(!ifMatch){
                    return  false;
                }

            }
            return  true;  //必须所有条件都满足才返回true
        }

        return false;
    }


    private  boolean   compareWithOperator(Long num1 ,String opt ,Long num2 ){
            switch (opt){
                case "eq": return num1==num2 ;
                case "neq": return num1!=num2 ;
                case "gte": return num1>=num2 ;
                case "lte": return num1<=num2 ;
                case "gt": return num1>num2 ;
                case "lt": return num1<num2 ;
            }
            return  false;
    }
}
